package yyy.ab.modules.generator.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yyy.ab.common.core.Query;
import yyy.ab.common.core.ResultBean;
import yyy.ab.common.exception.BadRequestException;
import yyy.ab.common.utils.FileUtil;
import yyy.ab.common.utils.StringUtils;
import yyy.ab.modules.generator.entity.ColumnInfo;
import yyy.ab.modules.generator.entity.GenConfig;
import yyy.ab.modules.generator.entity.vo.TableInfo;
import yyy.ab.modules.generator.mapper.GenConfigMapper;
import yyy.ab.modules.generator.service.GeneratorService;
import yyy.ab.modules.generator.mapper.ColumnInfoMapper;
import yyy.ab.modules.generator.utils.GenUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Zheng Jie
 * @date 2019-01-02
 */
@Service
@RequiredArgsConstructor
public class GeneratorServiceImpl implements GeneratorService {

    private DataSource dataSource;
    private final GenConfigMapper genConfigMapper;
    private final ColumnInfoMapper columnInfoMapper;

    @Override
    public Object getTables() {
        List<TableInfo> tableInfoList = genConfigMapper.findTableInfoList();
        return tableInfoList;
    }

    @Override
    public IPage<TableInfo> getTables(Map<String, Object> param) {
        Page<TableInfo> page = new Query<TableInfo>(param).getPage();

        return genConfigMapper.findTableInfoPage(page, param.get("tableName") == null ? null : String.valueOf(param.get("tableName")));
    }

    @Override
    @Transactional
    public List<ColumnInfo> getColumns(String tableName) {
        QueryWrapper<ColumnInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(tableName != null, "table_name", tableName);
        queryWrapper.orderByAsc("id");
        List<ColumnInfo> columnInfos = columnInfoMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(columnInfos)) {
            return columnInfos;
        } else {
            columnInfos = query(tableName);
            for (ColumnInfo columnInfo : columnInfos) {
                columnInfoMapper.insert(columnInfo);
            }
            return columnInfos;
        }
    }

    @Override
    public List<ColumnInfo> query(String tableName) {
        List<ColumnInfo> columnInfos = genConfigMapper.findColumnInfo(tableName);
        if (columnInfos != null && columnInfos.size() > 0) {
            for (ColumnInfo columnInfo : columnInfos) {
                if (GenUtil.PK.equalsIgnoreCase(columnInfo.getKeyType()) && GenUtil.EXTRA.equalsIgnoreCase(columnInfo.getExtra())) {
                    columnInfo.setNotNull(false);
                    columnInfo.setListShow(true);
                    columnInfo.setFormShow(true);
                }
            }
        }
        return columnInfos;
    }

    @Override
    public void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList) {
        // 第一种情况，数据库类字段改变或者新增字段
        for (ColumnInfo columnInfo : columnInfoList) {
            // 根据字段名称查找
            List<ColumnInfo> columns = columnInfos.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
            // 如果能找到，就修改部分可能被字段
            if (CollectionUtil.isNotEmpty(columns)) {
                ColumnInfo column = columns.get(0);
                column.setColumnType(columnInfo.getColumnType());
                column.setExtra(columnInfo.getExtra());
                column.setKeyType(columnInfo.getKeyType());
                if (StringUtils.isBlank(column.getRemark())) {
                    column.setRemark(columnInfo.getRemark());
                }
                columnInfoMapper.updateById(column);
            } else {
                // 如果找不到，则保存新字段信息
                columnInfoMapper.insert(columnInfo);
            }
        }
        // 第二种情况，数据库字段删除了
        for (ColumnInfo columnInfo : columnInfos) {
            // 根据字段名称查找
            List<ColumnInfo> columns = columnInfoList.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
            // 如果找不到，就代表字段被删除了，则需要删除该字段
            if (CollectionUtil.isEmpty(columns)) {
                columnInfoMapper.deleteById(columnInfo.getId());
            }
        }
    }

    @Override
    @Transactional
    public void save(List<ColumnInfo> columnInfos) {
        if (columnInfos != null && columnInfos.size() > 0) {
            for (ColumnInfo columnInfo : columnInfos) {
                if(columnInfo.getId()==null) {
                    columnInfoMapper.insert(columnInfo);
                }else{
                    columnInfoMapper.updateById(columnInfo);
                }
            }
        }
    }

    @Override
    public void generator(GenConfig genConfig, List<ColumnInfo> columns) {
        if (genConfig.getId() == null) {
            throw new BadRequestException("请先配置生成器");
        }
        try {
            GenUtil.generatorCode(columns, genConfig);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BadRequestException("生成失败，请手动处理已生成的文件");
        }
    }

    @Override
    public ResultBean preview(GenConfig genConfig, List<ColumnInfo> columns) {
        if (genConfig.getId() == null) {
            throw new BadRequestException("请先配置生成器");
        }
        List<Map<String, Object>> genList = GenUtil.preview(columns, genConfig);
        return ResultBean.success(genList);
    }

    @Override
    public void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response) {
        if (genConfig.getId() == null) {
            throw new BadRequestException("请先配置生成器");
        }
        try {
            File file = new File(GenUtil.download(columns, genConfig));
            String zipPath = file.getPath() + ".zip";
            ZipUtil.zip(file.getPath(), zipPath);
            FileUtil.downloadFile(request, response, new File(zipPath), true);
        } catch (IOException e) {
            throw new BadRequestException("打包失败");
        }
    }
}
